package com.gc.ip;

import java.awt.Color;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JComponent;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import com.gc.ip.util.IPAddressParseResult;
import com.gc.ip.util.IPAddressParser;

@SuppressWarnings("serial")
public class JIPAnyEditor extends JTextField implements IPEditor, PropertyChangeListener
{
	protected IPAddress ipAddress;
	
	protected boolean hasPrefixLength;
	protected IPType ipType;
	
	protected Color ipInvalidColor = null;
	protected Color ipV4Color = null;
	protected Color ipV6Color = null;
	
	public JIPAnyEditor(boolean hasPrefixLength, IPType ipType)
	{
		super();
		
		this.hasPrefixLength = hasPrefixLength;
		this.ipType = ipType;
		
		this.ipInvalidColor = Color.RED;
		this.ipV4Color = new Color(0, 150, 0);
		this.ipV6Color = new Color(150, 0, 150);
		
		//add IP Type property listener
		addPropertyChangeListener(IP_TYPE_PROPERTY, this);
			
		//add document listener to listen text changes
		this.getDocument().addDocumentListener(new ParseIPDocumentListener());
	}
	
	public JIPAnyEditor()
	{
		this(false, IPType.IPv4_v6);
	}
	
	@Override
	public IPAddress getIPAddress()
	{
		return ipAddress;
	}

	@Override
	public void setIPAddress(IPAddress ip)
	{		
		String text = "";
		if(ip != null)
		{
			text = ip.toString();
		}
		setText(text);
	}

	@Override
	public JComponent getUiComponent()
	{
		return this;
	}
	
	@Override
	public void propertyChange(PropertyChangeEvent event)
	{
		String propName = event.getPropertyName();
		
		//IP Type changed
		if(IP_TYPE_PROPERTY.equals(propName))
		{
			IPType newVal = (IPType)event.getNewValue();
			
			Color color = ipInvalidColor;
			if(newVal == IPType.IPv4)
			{
				color = ipV4Color;
			}
			else if(newVal == IPType.IPv6)
			{
				color = ipV6Color;
			}
			
			this.setForeground(color);
//			this.setBackground(color);
		}
	}
	
	private void parseIP(String text)
	{
		IPAddressParseResult result = new IPAddressParseResult();
		IPAddressParser.parse(text, hasPrefixLength, ipType, result);
		
		ipAddress = result.getIPAddress();

		putClientProperty(IP_ADDRESS_PROPERTY, ipAddress);
		putClientProperty(IP_TYPE_PROPERTY, result.getIPType());
		putClientProperty(TEXT_PROPERTY, text);
	}
	
	/**
	 * Called when the content of the editor changed
	 */
	private void contentChanged()
	{
		parseIP(this.getText());
	}

	private class ParseIPDocumentListener implements DocumentListener
	{
		/**
		 * Gives notification that there was an insert into the document. The
		 * range given by the DocumentEvent bounds the freshly inserted region.
		 * 
		 * @param e
		 *            the document event
		 */
		public void insertUpdate(DocumentEvent e)
		{
			contentChanged();
		}

		/**
		 * Gives notification that a portion of the document has been removed.
		 * The range is given in terms of what the view last saw (that is,
		 * before updating sticky positions).
		 * 
		 * @param e
		 *            the document event
		 */
		public void removeUpdate(DocumentEvent e)
		{
			contentChanged();
		}

		/**
		 * Gives notification that an attribute or set of attributes changed.
		 * 
		 * Called when the style of some of the text in the listened-to document changes. 
		 * This sort of event is fired only from a StyledDocument
		 *  — a PlainDocument does not fire these events.
		 * @param e
		 *            the document event
		 */
		public void changedUpdate(DocumentEvent e)
		{
			contentChanged();
		}
	}
}
